package io.github.wanggit.antrpc.console.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import io.github.wanggit.antrpc.commons.bean.RegisterBeanMethod;
import io.github.wanggit.antrpc.commons.utils.JsonUtils;
import io.github.wanggit.antrpc.console.dao.ProviderRateLimitingRepository;
import io.github.wanggit.antrpc.console.domain.ProviderRateLimiting;
import io.github.wanggit.antrpc.console.service.ProviderRateLimitingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Transactional
@Service
public class ProviderRateLimitingServiceImpl implements ProviderRateLimitingService {

    @Autowired private ProviderRateLimitingRepository providerRateLimitingRepository;

    @Override
    public void saveOrUpdate(ProviderRateLimiting providerRateLimiting) {
        String methodMd5 =
                ProviderRateLimiting.generateMethodMd5(
                        providerRateLimiting.getHostPort(),
                        providerRateLimiting.getClassName(),
                        providerRateLimiting.getMethodName(),
                        providerRateLimiting.getParameterTypeNames());
        ProviderRateLimiting record = providerRateLimitingRepository.findByMethodMd5(methodMd5);
        if (null == record) {
            record = new ProviderRateLimiting();
        }
        record.setClassName(providerRateLimiting.getClassName());
        record.setDurationInSeconds(providerRateLimiting.getDurationInSeconds());
        record.setHostPort(providerRateLimiting.getHostPort());
        record.setLimitValue(providerRateLimiting.getLimitValue());
        record.setClassMd5(
                ProviderRateLimiting.generateClassMd5(
                        providerRateLimiting.getHostPort(), providerRateLimiting.getClassName()));
        record.setMethodMd5(methodMd5);
        record.setMethodName(providerRateLimiting.getMethodName());
        record.setParameterTypeNames(providerRateLimiting.getParameterTypeNames());
        providerRateLimitingRepository.save(record);
    }

    @Override
    public Map<String, RegisterBeanMethod> findProviderRateLimiting(
            ProviderRateLimiting providerRateLimiting) {
        String classMd5 =
                ProviderRateLimiting.generateClassMd5(
                        providerRateLimiting.getHostPort(), providerRateLimiting.getClassName());
        List<ProviderRateLimiting> providerRateLimitingList =
                providerRateLimitingRepository.findAllByClassMd5(classMd5);
        return providerRateLimitingList.stream()
                .map(
                        it -> {
                            RegisterBeanMethod registerBeanMethod = new RegisterBeanMethod();
                            registerBeanMethod.setMethodName(it.getMethodName());
                            registerBeanMethod.setDurationInSeconds(it.getDurationInSeconds());
                            registerBeanMethod.setLimit(it.getLimitValue());
                            registerBeanMethod.setParameterTypeNames(
                                    JsonUtils.fromJson(
                                            it.getParameterTypeNames(),
                                            new TypeReference<List<String>>() {}));
                            registerBeanMethod.setClassName(it.getClassName());
                            return registerBeanMethod;
                        })
                .collect(Collectors.toMap(RegisterBeanMethod::toString, it -> it));
    }
}
